﻿using An_Im.Model;
using Microsoft.Vbe.Interop;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CORE = Microsoft.Office.Core;
using PPT = Microsoft.Office.Interop.PowerPoint;
using VBE = Microsoft.Vbe.Interop;

namespace An_Im.PowerV
{
    internal static class PowerVFrame
    {
        public static string PowerVTemplateFolderPath => Path.Combine(CoreManipulator.FolderPath, "PowerVFrameSource");

        /// <summary>
        /// 导入PowerV框架模板。
        /// </summary>
        /// <param name="vbproject"></param>
        public static void LoadPowerVFrameTemplate(VBE.VBProject vbproject)
        {
            //foreach (var file in Directory.GetFiles(PowerVTemplateFolderPath))
            //{
            //    // var m = vbproject.VBComponents.Add( VBE.vbext_ComponentType.vbext_ct_StdModule);
            //    vbproject.VBComponents.Import(file);
            //}

            HashSet<string> componentsHashSet = new HashSet<string>();
            HashSet<string> refURLHashSet = new HashSet<string>();

            foreach (VBE.VBComponent item in vbproject.VBComponents)
            {
                componentsHashSet.Add(item.Name);
            }

            foreach (VBE.Reference item in vbproject.References)
            {
                componentsHashSet.Add(item.Guid);
            }

            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, "API", An_Im.Properties.PowerVSource.API);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsAnim", An_Im.Properties.PowerVSource.clsAnim);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsAnimNode", An_Im.Properties.PowerVSource.clsAnimNode);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsAnimNodePath", An_Im.Properties.PowerVSource.clsAnimNodePath);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsAnimNodes", An_Im.Properties.PowerVSource.clsAnimNodes);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsCursor", An_Im.Properties.PowerVSource.clsCursor);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsFiles", An_Im.Properties.PowerVSource.clsFiles);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsGlobalBox", An_Im.Properties.PowerVSource.clsGlobalBox);
            //AddComponent(componentsHashSet,vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsInput", An_Im.Properties.PowerVSource.clsInput);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsPVApplication", An_Im.Properties.PowerVSource.clsPVApplication);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsRGB", An_Im.Properties.PowerVSource.clsRGB);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsSlideShow", An_Im.Properties.PowerVSource.clsSlideShow);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsTimer", An_Im.Properties.PowerVSource.clsTimer);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "clsTools", An_Im.Properties.PowerVSource.clsTools);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, "DSE", An_Im.Properties.PowerVSource.DSE);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, "main", An_Im.Properties.PowerVSource.main);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, "main_events", An_Im.Properties.PowerVSource.main_events);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "PowerV", An_Im.Properties.PowerVSource.PowerV);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, "pu", An_Im.Properties.PowerVSource.pu);
            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, "pv", An_Im.Properties.PowerVSource.pv);

            AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, "vector2i_C", An_Im.Properties.PowerVSource.vector2i_C);


            //AddReference(refURLHashSet, vbproject, "{000204EF-0000-0000-C000-000000000046}", 4, 2);
            //AddReference(refURLHashSet, vbproject, "{91493440-5A91-11CF-8700-00AA0060263B}", 2, 12);
            //AddReference(refURLHashSet, vbproject, "{00020430-0000-0000-C000-000000000046}", 2, 0);
            //AddReference(refURLHashSet, vbproject, "{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}", 2, 8);
            AddReference(refURLHashSet, vbproject, "{0D452EE1-E08F-101A-852E-02608C4D0BB4}", 2, 0);
            AddReference(refURLHashSet, vbproject, "{B691E011-1797-432E-907A-4D8C69339129}", 6, 1);
            AddReference(refURLHashSet, vbproject, "{420B2830-E718-11CF-893D-00A0C9054228}", 1, 0);
            AddReference(refURLHashSet, vbproject, "{F5078F18-C551-11D3-89B9-0000F81FE221}", 3, 0);
            AddReference(refURLHashSet, vbproject, "{3F4DACA7-160D-11D2-A8E9-00104B365C9F}", 1, 0);
            AddReference(refURLHashSet, vbproject, "{0002E157-0000-0000-C000-000000000046}", 5, 3);

        }

        private static VBE.VBComponent AddComponent(HashSet<string> hashset, VBE.VBProject vbproject, VBE.vbext_ComponentType type, string name, string content)
        {
            if (hashset.Contains(name)) return null;

            var result = vbproject.VBComponents.Add(type);
            result.Name = name;
            ClearCodeModule(result.CodeModule);
            result.CodeModule.AddFromString(content);
            return result;
        }

        private static void ClearCodeModule(CodeModule codeModule)
        {
            var count = codeModule.CountOfLines;
            if (count != 0)
                codeModule.DeleteLines(1, count);
        }

        private static VBE.Reference AddReference(HashSet<string> hashset, VBE.VBProject vbproject, string guid, int major, int minor)
        {
            try
            {
                if (hashset.Contains(guid))
                    return null;
                else
                    return vbproject.References.AddFromGuid(guid, major, minor);
            }catch
            {
                return null;
            }
           
        }

        // 导入自定义数据信息。
        public static void LoadInCustomData(PPT.Presentation pres, VBE.VBProject vbproject)
        {
            var xmlpart = GetCustomXMLPart(pres, nameof(PowerVInnerInfomation));
            if (xmlpart == null) return;
            var bytes = Encoding.UTF8.GetBytes(xmlpart.XML);
            var memStream = new MemoryStream(bytes);

            var xmlSeri = new System.Xml.Serialization.XmlSerializer(typeof(PowerVInnerInfomation));
         
            var pvinfo = xmlSeri.Deserialize(memStream) as PowerVInnerInfomation;
            memStream.Close();
            HashSet<string> componentsHashSet = new HashSet<string>();
            HashSet<string> refURLHashSet = new HashSet<string>();

            foreach (VBE.VBComponent item in vbproject.VBComponents)
            {
                componentsHashSet.Add(item.Name);
            }

            foreach (VBE.Reference item in vbproject.References)
            {
                componentsHashSet.Add(item.Guid);
            }


            foreach (var mpart in pvinfo.Modules)
            {
                switch (mpart.ModuleType)
                {
                    case ModuleType.Class:
                        AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_ClassModule, mpart.Name, mpart.Code);

                        break;
                    case ModuleType.Std:
                        AddComponent(componentsHashSet, vbproject, VBE.vbext_ComponentType.vbext_ct_StdModule, mpart.Name, mpart.Code);
                        break;
                    default:
                        break;
                }
               
            }

            //AddReference(refURLHashSet, vbproject, "{000204EF-0000-0000-C000-000000000046}", 4, 2);
            //AddReference(refURLHashSet, vbproject, "{91493440-5A91-11CF-8700-00AA0060263B}", 2, 12);
            //AddReference(refURLHashSet, vbproject, "{00020430-0000-0000-C000-000000000046}", 2, 0);
            //AddReference(refURLHashSet, vbproject, "{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}", 2, 8);
            AddReference(refURLHashSet, vbproject, "{0D452EE1-E08F-101A-852E-02608C4D0BB4}", 2, 0);
            AddReference(refURLHashSet, vbproject, "{B691E011-1797-432E-907A-4D8C69339129}", 6, 1);
            AddReference(refURLHashSet, vbproject, "{420B2830-E718-11CF-893D-00A0C9054228}", 1, 0);
            AddReference(refURLHashSet, vbproject, "{F5078F18-C551-11D3-89B9-0000F81FE221}", 3, 0);
            AddReference(refURLHashSet, vbproject, "{3F4DACA7-160D-11D2-A8E9-00104B365C9F}", 1, 0);
            AddReference(refURLHashSet, vbproject, "{0002E157-0000-0000-C000-000000000046}", 5, 3);

        }

        private static CORE.CustomXMLPart GetCustomXMLPart(PPT.Presentation pres, string xmlName)
        {
            var xmlparts = pres.CustomXMLParts;
             
            foreach (CORE.CustomXMLPart xmlpart in xmlparts)
            {
                if (xmlpart.DocumentElement == null) continue;
                if (xmlpart.DocumentElement.BaseName == xmlName)
                    return xmlpart;
            }
            return null;
        }

        /// <summary>
        /// 保存自定义数据。
        /// </summary>
        /// <param name="pres"></param>
        /// <param name="components"></param>
        public static void SaveCustomData(PPT.Presentation pres, VBE.VBComponents components)
        {
            var pvinfo = new PowerVInnerInfomation();
            pvinfo.Name = "PowerV Frame";
            pvinfo.Modules = new List<ModulePart>();

            foreach (VBE.VBComponent comp in components)
            {
                var mod = new ModulePart();
                if (comp.Type == vbext_ComponentType.vbext_ct_StdModule)
                {
                    mod.ModuleType = ModuleType.Std;

                }
                else if (comp.Type == vbext_ComponentType.vbext_ct_ClassModule)
                {
                    mod.ModuleType = ModuleType.Class;
                }
                else
                {
                    continue;
                }

                mod.Code = comp.CodeModule.GetAllCode();
                mod.Name = comp.Name;
                pvinfo.Modules.Add(mod);
            }

            var memStream = new MemoryStream();
            var xmlSeri = new System.Xml.Serialization.XmlSerializer(typeof(PowerVInnerInfomation));
            xmlSeri.Serialize(memStream, pvinfo);
            memStream.Close();
            var bytes = memStream.ToArray();
            var xmlString = Encoding.UTF8.GetString(bytes);

            var xmlpart = GetCustomXMLPart(pres, nameof(PowerVInnerInfomation));
            if (xmlpart != null)
            {
                xmlpart.Delete();
            }
            var newCustomPart = pres.CustomerData.Add();
            newCustomPart.LoadXML(xmlString);// 载入 xml

        }

    }
}
